// Copyright: Personal possession of Nguyen Minh Kha
// Decription: This class use to manage user input from keyboard and mouse
// Date time: 09:30AM, 07/08/2011(mm/dd/yyyy)
// License: free source
// Version: 1.0
// Writer: Nguyen Minh Kha
// Sample usage:
//   Control control;
//   ...
//   /*in game loop*/
//   control.CatchEvent();

#include "control.h"

Control* Control::control;

Control::Control(void)
{
  this->mode = ONE; // default mode
}


Control::~Control(void)
{

}


void Control::Acquire() {
  HRESULT hr = deviceKeyboard->Acquire();
  if(hr != DI_OK)
	  printf("Keyboard acquire fail");
  hr = deviceMouse->Acquire();
  if(hr != DI_OK)
	  printf("Mouse acquire fail");
}


void Control::Release() {
  deviceKeyboard->Unacquire();
  deviceMouse->Unacquire();
  dinput->Release();
}


int Control::Init(HINSTANCE hInstance, HWND hWnd) {
  //this->controlled_list = list; // controlable list objects
  control = this; // use to access control instance from another class
  hResult = DirectInput8Create(
      hInstance, 
      DIRECTINPUT_VERSION,
      IID_IDirectInput8, // direct interface
      (void**)&dinput,
      NULL);
  this->hWnd = hWnd;
  if(hResult != DI_OK) {
    printf("Create direct input interface fail.");
    return 1;
  }
  //
  // Keyboard
  //

  // create keyboard device
  hResult = dinput->CreateDevice(GUID_SysKeyboard, &deviceKeyboard, NULL);
  if(hResult != DI_OK) {
    printf("Create direct input device - keyboard fail.");
    return 1;
  }
  // Set data format for keyboard
  hResult = deviceKeyboard->SetDataFormat(&c_dfDIKeyboard);
  if(hResult != DI_OK) {
    printf("Set data format for keyboard fail.");
    return 1;
  }
  // setup buffer
  dipdw.diph.dwSize = sizeof(dipdw);
  dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
  dipdw.diph.dwObj = 0;
  dipdw.diph.dwHow = DIPH_DEVICE;
  dipdw.dwData = KEY_BUFFER_LENGTH;
  deviceKeyboard->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph);
  keyEvents = new DIDEVICEOBJECTDATA[KEY_BUFFER_LENGTH];
  numberOfKeyEvent = KEY_BUFFER_LENGTH;
  // set cooperative level
  hResult = deviceKeyboard->SetCooperativeLevel(hWnd, 
	  DISCL_NONEXCLUSIVE | DISCL_FOREGROUND );
  if(hResult != DI_OK) {
    printf("Set cooperative level for keyboard fail.");
    return 1;
  }

  //
  // Mouse
  //

  // create mouse device
  hResult = dinput->CreateDevice(GUID_SysMouse, &deviceMouse, NULL);
  if(hResult != DI_OK) {
    printf("Create direct input device - mouse fail.");
    return 1;
  }
  // Set data format for mouse
  hResult = deviceMouse->SetDataFormat(&c_dfDIMouse);
  if(hResult != DI_OK) {
    printf("Set data format for mouse fail.");
    return 1;
  }
  // set cooperative level
  hResult = deviceMouse->SetCooperativeLevel(hWnd, 
      DISCL_NONEXCLUSIVE | DISCL_FOREGROUND  );
  if(hResult != DI_OK) {
    printf("Set cooperative level for keyboard fail.");
    return 1;
  }
  this->Acquire();
  return 0;
}


void Control::CatchEvent() {
  // Get keyboard state
  numberOfKeyEvent = KEY_BUFFER_LENGTH;
  LPDIDEVICEINSTANCEW info = new DIDEVICEINSTANCEW;
  deviceKeyboard->GetDeviceInfo(info);

  hResult = deviceKeyboard->GetDeviceData(
      sizeof(DIDEVICEOBJECTDATA),
      keyEvents, &numberOfKeyEvent, 0);
  
  if (hResult != DI_OK)
    return;
  // Get mouse state
  switch(this->mode) {
  case ONE: {
    this->Control_One();
    break;
    }
  case TWO: {
    this->Control_Two();
    break;
    }
  case THREEE: {
    this->Control_Three();
    break;
    }
  }
}


void Control::Control_One() {
  for (DWORD i = 0; i < numberOfKeyEvent; i++) {
    int keyCode = keyEvents[i].dwOfs;
    int keyState = keyEvents[i].dwData;
    if ((keyState & 0x80) > 0) { // Key down event
      // ` key, view log
      if(keyCode == DIK_GRAVE) {
        
        
      }
      // Esc key
      if(keyCode == DIK_ESCAPE) {
        int messageBoxResult = 0;
        messageBoxResult = MessageBox(
          hWnd, EXIT_CONFIRM_TEXT, 
          EXIT_CONFIRM_CAPTION,
          MB_OKCANCEL | MB_ICONQUESTION);
        if (messageBoxResult == IDOK) {
          PostMessage(hWnd, WM_QUIT, 0, 0); 
        
        } 
      }

	  //
	  if(keyCode == DIK_DELETE)
	  {
		  printf("test");
		  
	  }
      // invoke objects to seft execute its event
      // this->controlled_list->Controls(true, keyCode);
    } else { // Key up event
      //this->controlled_list->Controls(false, keyCode);
    }
  }
}


void Control::Control_Two() {
  if (KEY_DOWN(VK_ESCAPE)) {
      int messageBoxResult = 0;
      messageBoxResult = MessageBox(hWnd, EXIT_CONFIRM_TEXT, EXIT_CONFIRM_CAPTION,
                 MB_OKCANCEL | MB_ICONQUESTION);
      if (messageBoxResult == IDOK) {
        PostMessage(hWnd, WM_QUIT, 0, 0); 
      }
  }
}


void Control::Control_Three() {
  if (KEY_DOWN(VK_ESCAPE)) {
          int messageBoxResult = 0;
      messageBoxResult = MessageBox(hWnd, EXIT_CONFIRM_TEXT, EXIT_CONFIRM_CAPTION,
                 MB_OKCANCEL | MB_ICONQUESTION);
      if (messageBoxResult == IDOK) {
        PostMessage(hWnd, WM_QUIT, 0, 0); 
      }
  }
}
